package com.richard.base.net.utils

import android.os.Environment
import com.richard.base.net.common.NetComponent
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.security.GeneralSecurityException
import java.security.KeyStore
import java.security.SecureRandom
import java.security.cert.CertificateException
import java.security.cert.CertificateFactory
import java.util.*
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.TrustManagerFactory

/**
 * **************************************
 * 项目名称:kaishustory
 *
 * @Author guanhuawei
 * 邮箱：guanhuawei@ksjgs
 * 创建时间: 2020/3/9   22:50
 * 用途
 * 用于加载多证书
 * **************************************
 */
class SSLSocketFactoryUtils {
    lateinit var trustManagers: Array<TrustManager>
        private set

    fun getSSlSocketFrctoryByPaths(): SSLSocketFactory? {
        val certificates: MutableList<InputStream> = ArrayList()
        //首先加载从assets里面的证书，如果有效就直接使用
        certificates.addAll(NetComponent.getAssetsPems())
        //如果asset证书没有效则使用从网络下载的
        val file = File(mSDPath)
        if (file != null && file.exists()) {
            val files = file.listFiles()
            if (files != null) {
                for (i in files.indices) {
                    val localFile = files[i]
                    //读取本地的
                    val inStream = AseUtils.decrypt(localFile, "12345678g01234ab")
                    if (inStream != null) {
                        certificates.add(inStream)
                    }
                }
            }
        }
        return if (certificates != null && certificates.size > 0) {
            getSSLSocketFactory(certificates)
        } else null
    }

    private fun getSSLSocketFactory(certificates: List<InputStream>?): SSLSocketFactory? {
        if (certificates == null || certificates.isEmpty()) {
            return null
        }
        try {
            val certificateFactory =
                CertificateFactory.getInstance("X.509")
            // Put the certificates a key store.
            val password = "kaishu2099".toCharArray() // Any password will work.
            val keyStore = newEmptyKeyStore(password)
            var index = 0
            for (certificate in certificates) {
                val certificateAlias = Integer.toString(index++)
                keyStore.setCertificateEntry(
                    certificateAlias,
                    certificateFactory.generateCertificate(certificate)
                )
            } // Use it to b
            val sslContext = SSLContext.getInstance("TLS")
            val trustManagerFactory =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
            trustManagerFactory.init(keyStore)
            trustManagers = trustManagerFactory.trustManagers
            sslContext.init(null, trustManagers, SecureRandom())
            return sslContext.socketFactory
        } catch (e: CertificateException) {
            e.printStackTrace()
        } catch (e: GeneralSecurityException) {
            e.printStackTrace()
        }
        return null
    }

    @Throws(GeneralSecurityException::class)
    private fun newEmptyKeyStore(password: CharArray): KeyStore {
        return try {
            val keyStore =
                KeyStore.getInstance(KeyStore.getDefaultType())
            val `in`: InputStream? =
                null // By convention, 'null' creates an empty key store.
            keyStore.load(`in`, password)
            keyStore
        } catch (e: IOException) {
            throw AssertionError(e)
        }
    }

    companion object {
        private val mSDPath = Environment.getExternalStorageDirectory().absolutePath + "/pem/"

        val instance: SSLSocketFactoryUtils by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            SSLSocketFactoryUtils()
        }
    }
}